package com.shop.admin.service.pink;


import com.alibaba.fastjson.JSON;
import com.shop.admin.dao.pink.AutoPinkDao;
import com.shop.admin.dao.pink.StorePinkConfigDao;
import com.shop.admin.dao.pink.StorePinkDao;
import com.shop.admin.dao.user.UserDao;
import com.shop.admin.dao.user.UserPinkBillDao;
import com.shop.admin.dao.user.UserPinkInfoDao;
import com.shop.admin.dao.store.StoreProductAttrValueDao;
import com.shop.admin.dao.store.StoreProductDao;
import com.shop.admin.service.user.UserBillService;
import com.shop.common.enums.TrueFalseEnum;
import com.shop.common.enums.pay.PayStatusEnum;
import com.shop.common.enums.pay.PayTypeEnum;
import com.shop.common.enums.user.AccountTypeEnum;
import com.shop.common.enums.user.BillTableNameEnum;
import com.shop.common.enums.user.IncomeTypeEnum;
import com.shop.domain.pink.StorePink;
import com.shop.domain.pink.StorePinkConfig;
import com.shop.domain.pink.UserPinkInfo;
import com.shop.domain.store.StoreProduct;
import com.shop.domain.user.User;
import com.shop.util.DateUtil;
import com.shop.util.RandomUtil;
import com.shop.web.cache.RedisCache;
import com.shop.web.response.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
@Transactional
public class StorePinkService {

    @Autowired
    private StorePinkDao storePinkDao;

    @Autowired
    private AutoPinkDao autoPinkDao;

    @Autowired
    private StorePinkConfigDao storePinkConfigDao;

    @Autowired
    private UserPinkBillDao userPinkBillDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserPinkInfoDao userPinkInfoDao;

    @Autowired
    private UserBillService userBillService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private StoreProductDao storeProductDao;

    @Autowired
    private StoreProductAttrValueDao storeProductAttrValueDao;


    /**
     * 执行拼团
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public BaseResponse exeStorePink() {

        long time=System.currentTimeMillis();

        //1,查询拼团配置信息
        StorePinkConfig storePinkConfig = storePinkConfigDao.findSingle(1l);

        if(storePinkConfig.getStatus().equals(TrueFalseEnum.FALSE.getCode())
          || !DateUtil.isEffectiveDate(DateUtil.parseTime(DateUtil.formatTime(new Date())),DateUtil.parseTime(storePinkConfig.getStartTime()),DateUtil.parseTime(storePinkConfig.getEndTime()))){
            return new BaseResponse();
        }

        redisCache.set("exeStorePinkIng"+storePinkConfig.getId(), "exeIng", 300);

        long time1=System.currentTimeMillis();
        // 查询所有拼团人数
        int allCount = storePinkDao.getAllPinkCount(storePinkConfig.getId());
        long time2=System.currentTimeMillis();
        //2，黑名单中奖处理
        int black_num = storePinkDao.updatePinkBlack(storePinkConfig.getId());
        long time3=System.currentTimeMillis();
        //3,第五单拼中用户订单
        List<StorePink> fiveList =  storePinkDao.findAllPinkFive(storePinkConfig.getId(),storePinkConfig.getPinzhongNum());
        long time4=System.currentTimeMillis();

        //1~4超过未中奖次数 中奖
        List<StorePink> maxList = storePinkDao.findMaxNotPzNum(storePinkConfig.getId(),storePinkConfig.getRoundMaxPzNum());
        long time41=System.currentTimeMillis();
        //4,1~4单中奖
        //计算1~4单应该拼中人数 =总人数*中奖概率-黑名单中奖-第五单人数
        int hasNum =  ((BigDecimal.valueOf(allCount).multiply(storePinkConfig.getZjRate())).divide(new BigDecimal(100))).intValue() - black_num - fiveList.size() - maxList.size();
        if(hasNum<0){
            hasNum = 0;
        }
        List<StorePink> OneToFourList = storePinkDao.findAllPinkOneToFour(storePinkConfig.getId(),storePinkConfig.getPrizeNumber(),hasNum);
        long time5=System.currentTimeMillis();

        //循环修改标记

        List<Long> fiveIds = new ArrayList<>();
        //第五单用户
        for(StorePink sp:fiveList){
            fiveIds.add(sp.getId());
        }
        //1~4单超限用户
        for(StorePink mx:maxList){
            fiveIds.add(mx.getId());
        }
        //1~4单用户
        for(StorePink one:OneToFourList){
            fiveIds.add(one.getId());
        }
        if(fiveIds.size()>0){
            storePinkDao.updatePinkFives(fiveIds);
        }
        long time6=System.currentTimeMillis();

        //未中奖用户修改状态为未中奖
        int notPzNum = storePinkDao.updateNotPinkStatus(storePinkConfig.getId());
        long time7=System.currentTimeMillis();
        //自动拼团表添加中奖记录
        int addAutoPinkNum =  autoPinkDao.addAutoPinkByZj(storePinkConfig.getId());
        long time8=System.currentTimeMillis();

        //未中奖添加拼团流水记录
        int notZjNum =  userPinkBillDao.addNotPzUserBill(storePinkConfig.getId());
        long time9=System.currentTimeMillis();

        //未中奖  用户增加佣金
        int notZjUserNum = userDao.updateNotPz(storePinkConfig.getId(),storePinkConfig.getRetPrice());
        long time10=System.currentTimeMillis();

        //未中奖 修改总未中奖次数  单轮未中次数
        int notZjPinkInfoNum = userPinkInfoDao.updateNotPzUserPinkInfo(storePinkConfig.getId());
        long time11=System.currentTimeMillis();

        //已中奖 修改总中奖次数和拼团轮数
        int zjPinkInfoNum = userPinkInfoDao.updatePzUserPinkInfo(storePinkConfig.getId());
        long time12=System.currentTimeMillis();

        //中奖修改 订单状态信息
        int pzSuccessNum = storePinkDao.updatePinkSuccessAddPinkNum(storePinkConfig.getId());
        long time13=System.currentTimeMillis();

        //未中奖 订单状态信息
        int notPzUpdateNum = storePinkDao.updateNotPzPink(storePinkConfig.getId(),storePinkConfig.getRetPrice());
        long time14=System.currentTimeMillis();

        int zj_num = storePinkConfigDao.AddPinkNum(storePinkConfig.getId());

        //删除redis 执行状态标记
        redisCache.del("exeStorePinkIng"+storePinkConfig.getId());


        log.info("配置加载时间:"+(time1-time)+"ms"+ JSON.toJSONString(storePinkConfig));
        log.info("查询总人数耗时："+(time2-time1)+"ms,拼团总人数"+allCount);
        log.info("黑名单中奖标记耗时："+(time3-time1)+"ms,人数："+black_num);
        log.info("第五单中奖耗时："+(time4-time3)+"ms,人数："+fiveList.size());
        log.info("一至四单超限中奖耗时："+(time41-time4)+"ms,人数："+maxList.size());
        log.info("一至四单中奖耗时："+(time5-time41)+"ms,人数："+OneToFourList.size());
        log.info("中奖标记耗时："+(time6-time5)+"ms");
        log.info("标记未中奖订单耗时："+(time7-time6)+"ms：人数："+notPzNum);
        log.info("拼中信息添加耗时："+(time8-time7)+"ms：记录数"+addAutoPinkNum);
        log.info("未中奖添加记录耗时："+(time9-time8)+"ms，记录数"+notZjNum);
        log.info("未中奖增加佣金耗时："+(time10-time9)+"ms，记录数"+notZjUserNum);
        log.info("未中奖修改总未中奖次数耗时："+(time11-time10)+"ms，记录数"+notZjPinkInfoNum);
        log.info("已中奖修改总中奖次数和拼团轮数耗时："+(time12-time11)+"ms，记录数"+zjPinkInfoNum);
        log.info("修改中奖订单状态耗时："+(time13-time12)+"ms，记录数"+pzSuccessNum);
        log.info("修改未中奖订单状态耗时："+(time14-time13)+"ms，记录数"+notPzUpdateNum);
        log.info("拼团总耗时:"+(time14-time));
        //续拼
        this.autoPink(storePinkConfig.getId());
        long time15=System.currentTimeMillis();
        log.info("拼团续拼总耗时:"+(time15-time));

        return new BaseResponse();
    }


    /**
     * 自动续拼
     * @return
     */
    public BaseResponse autoPink(Long pinkId){
        //查询需要续拼订单
        List<UserPinkInfo> userPinkInfos = userPinkInfoDao.queryNeedPtPinkInfo(pinkId);

        // 获取拼团配置信息
        StorePinkConfig pinkConfig = storePinkConfigDao.findSingle(pinkId);

        log.info("--- 续拼订单共计{}条 ---", userPinkInfos.size());

        long start = System.currentTimeMillis();

        for(UserPinkInfo u:userPinkInfos){

            if(TrueFalseEnum.TRUE.getCode() == u.getIsAutoPt() && u.getAutoProductId() != 0 &&u.getAutoProductAttrValueId() != 0 && u.getAutoAddressId() !=0){
                //按配置几率实现断拼
                if(RandomUtil.randomNumberRangeIn(1,100) > pinkConfig.getBreakPinkRate()){
                     this.autoCreateStorePink(u,pinkConfig);
                 }else{
                    userPinkInfoDao.updateAutoPinkFailInfo(u.getId(),"商品原因续拼失败");
                 }
            }else{
                userPinkInfoDao.updateAutoPinkFailInfo(u.getId(),"自动续拼未打开");
            }
        }

        long end = System.currentTimeMillis();
        log.info("--- 续拼订单消耗时间共计{}ms ---", (end - start));

        return new BaseResponse();
    }

    /**
     * 自动续聘创建订单
     * @param userPinkInfo
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public BaseResponse autoCreateStorePink(UserPinkInfo userPinkInfo,StorePinkConfig pinkConfig){

        // 用户当前是否有正常拼团的记录
        int count = storePinkDao.countPinking(userPinkInfo.getUid(), userPinkInfo.getPinkId());
        if(count >= 1) {
            userPinkInfoDao.updateAutoPinkFailInfo(userPinkInfo.getId(),"您已在该拼团中，请勿重复拼团！");
            return new BaseResponse();
        }


        User user = userDao.findSingle(userPinkInfo.getUid());

        //更新之后金额
        BigDecimal refreshPrice = user.getBalance().subtract(pinkConfig.getPrice());

        //限制下架商品不能续拼
        StoreProduct storeProduct = storeProductDao.findSingle(userPinkInfo.getAutoProductId());
        if(null == storeProduct || storeProduct.getIsShow() == TrueFalseEnum.FALSE.getCode()){
            userPinkInfoDao.updateAutoPinkFailInfo(userPinkInfo.getId(),"商品已下架！");
            return new BaseResponse();
        }

    /*    //商品规格库存不够限制
        StoreProductAttrValue storeProductAttrValue = storeProductAttrValueDao.findSingle(userPinkInfo.getAutoProductAttrValueId());
        if(null == storeProductAttrValue || storeProductAttrValue.getStock() == 0){
            userPinkInfoDao.updateAutoPinkFailInfo(userPinkInfo.getId(),"当前续拼商品规格库存不够！");
            return new BaseResponse();
        }*/

        //当前余额需要最后判断处理
        int subtractRows = userDao.subtractBalance(userPinkInfo.getUid(), pinkConfig.getPrice());
        if(subtractRows <= 0) {
            userPinkInfoDao.updateAutoPinkFailInfo(userPinkInfo.getId(),"余额不足！");
            return new BaseResponse();
        }

        // 订单号
        String orderNo = RandomUtil.generateId7OrderNo("A",user.getId());

        //保存拼团订单
        StorePink pink = new StorePink();
        pink.setUid(userPinkInfo.getUid());
        pink.setPinkId(userPinkInfo.getPinkId());
        pink.setProductId(userPinkInfo.getAutoProductId());
        pink.setProductAttrValueId(userPinkInfo.getAutoProductAttrValueId());
        pink.setPrice(pinkConfig.getPrice());
        pink.setTotalPrice(pinkConfig.getPrice());
        pink.setOrderNo(orderNo);
        pink.setStorePinkNum(userPinkInfo.getPtNum());
        pink.setUserAddressId(userPinkInfo.getAutoAddressId());
        pink.setStatus(PayStatusEnum.SUCCESS.getValue());
        pink.setPayCode(PayTypeEnum.YUE.getCode());
        pink.setPayType(PayTypeEnum.YUE.getType());
        pink.setPayTime(new Date());
        pink.setCreateTime(new Date());
        storePinkDao.save(pink);

        //增加用户交易流水
        userBillService.addUserBill(userPinkInfo.getUid(), pinkConfig.getPrice(), pink.getId(), BillTableNameEnum.AUTOPINK.getKey(), user.getBalance(),
                refreshPrice, IncomeTypeEnum.EXPEND.getKey(), AccountTypeEnum.BALANCE.getKey(),
                "参与自动续拼", "参与自动续拼，扣除余额" + pinkConfig.getPrice() + "元");

        return new BaseResponse();
    }
}
